﻿
Imports std
Imports sub_nodes_property = osi.fs.cached_set_int64_property

Partial Public Class node
    Partial Private Class internal_property_names
        Public Const sub_nodes As String = "sbn"
    End Class

    Public Delegate Function workon_sub_nodes_d(ByVal id As Int64,
                                                ByVal [continue] As pointer(Of Boolean)) As eventComb

    Private Function workon_sub_nodes(ByVal s As [set](Of Int64),
                                      ByVal d As workon_sub_nodes_d) As eventComb
        assert(Not d Is Nothing)
        Dim it As [set](Of Int64).iterator = Nothing
        Dim ec As eventComb = Nothing
        Dim [continue] As pointer(Of Boolean) = Nothing
        Return New eventComb(Function() As Boolean
                                 If s Is Nothing OrElse s.size() = 0 Then
                                     Return goto_end()
                                 Else
                                     [continue] = New pointer(Of Boolean)()
                                     it = s.begin()
                                     Return goto_next()
                                 End If
                             End Function,
                             Function() As Boolean
                                 If it <> s.end() Then
                                     eva([continue], False)
                                     ec = d(+it, [continue])
                                     Return waitfor(ec) AndAlso
                                            goto_next()
                                 Else
                                     Return goto_end()
                                 End If
                             End Function,
                             Function() As Boolean
                                 If ec.end_result() Then
                                     If +[continue] Then
                                         it += 1
                                         Return goto_prev()
                                     Else
                                         Return goto_end()
                                     End If
                                 Else
                                     Return False
                                 End If
                             End Function)
    End Function

    Public Function workon_sub_nodes(ByVal d As workon_sub_nodes_d) As eventComb
        Return workon_sub_nodes(CType(Nothing, void), d)
    End Function

    Public Function workon_sub_nodes(ByVal init As void,
                                     ByVal d As workon_sub_nodes_d) As eventComb
        assert(Not d Is Nothing)
        Dim sn As pointer(Of [set](Of Int64)) = Nothing
        Dim ec As eventComb = Nothing
        Return New eventComb(Function() As Boolean
                                 sn = New pointer(Of [set](Of Int64))()
                                 void_(init)
                                 ec = sub_nodes(sn)
                                 Return waitfor(ec) AndAlso
                                        goto_next()
                             End Function,
                             Function() As Boolean
                                 If ec.end_result() Then
                                     ec = workon_sub_nodes(+sn, d)
                                     Return waitfor(ec) AndAlso
                                            goto_next()
                                 Else
                                     Return False
                                 End If
                             End Function,
                             Function() As Boolean
                                 Return ec.end_result() AndAlso
                                        goto_end()
                             End Function)
    End Function

    Public Function sub_nodes(ByVal output As pointer(Of vector(Of String))) As eventComb
        Dim rtn As vector(Of String) = Nothing
        Dim pn As pointer(Of String) = Nothing
        Dim ec As eventComb = Nothing
        Return workon_sub_nodes(Sub()
                                    rtn = New vector(Of String)()
                                    pn = New pointer(Of String)()
                                    eva(output, rtn)
                                End Sub,
                                Function(id As Int64, [continue] As pointer(Of Boolean)) As eventComb
                                    Return New eventComb(
                                                Function() As Boolean
                                                    pn.clear()
                                                    ec = fs.name(id, pn)
                                                    Return waitfor(ec) AndAlso
                                                           goto_next()
                                                End Function,
                                                Function() As Boolean
                                                    Return (Not ec.end_result() OrElse rtn.push_back(+pn)) AndAlso
                                                           eva([continue], True) AndAlso
                                                           goto_end()
                                                End Function)
                                End Function)
    End Function

    Private Shared Function match_node_name(ByVal name As String,
                                            ByVal output As pointer(Of node),
                                            Optional ByVal found As pointer(Of Boolean) = Nothing) _
                                           As workon_sub_nodes_d
        Return Function(id As Int64, [continue] As pointer(Of Boolean)) As eventComb
                   Dim f As Boolean = False
                   Dim n As pointer(Of String) = Nothing
                   n = New pointer(Of String)()
                   Dim ec As eventComb = Nothing
                   Return New eventComb(Function() As Boolean
                                            n.clear()
                                            ec = fs.name(id, n, output)
                                            Return waitfor(ec) AndAlso
                                                   goto_next()
                                        End Function,
                                        Function() As Boolean
                                            Return eva(f, ec.end_result() AndAlso strsame(name, +n)) AndAlso
                                                   eva([continue], Not f) AndAlso
                                                   eva(found, f) AndAlso
                                                   goto_end()
                                        End Function)
               End Function
    End Function

    Public Function find_sub_node(ByVal name As String, ByVal output As pointer(Of node)) As eventComb
        Return workon_sub_nodes(match_node_name(name, output))
    End Function

    Private Function find_create_sub_node(ByVal s As [set](Of Int64),
                                          ByVal name As String,
                                          ByVal output As pointer(Of node)) As eventComb
        assert(Not s Is Nothing)
        Dim found As pointer(Of Boolean) = Nothing
        Dim ec As eventComb = Nothing
        Return New eventComb(Function() As Boolean
                                 found = New pointer(Of Boolean)(False)
                                 Return waitfor(workon_sub_nodes(
                                                    s,
                                                    match_node_name(name, output, found))) AndAlso
                                        goto_next()
                             End Function,
                             Function() As Boolean
                                 If +found Then
                                     Return goto_end()
                                 Else
                                     If output Is Nothing Then
                                         output = New pointer(Of node)()
                                     End If
                                     ec = fs.add(output)
                                     Return waitfor(ec) AndAlso
                                            goto_next()
                                 End If
                             End Function,
                             Function() As Boolean
                                 If ec.end_result() Then
                                     assert(Not +output Is Nothing)
                                     ec = (+output).set_name(name)
                                     Return waitfor(ec) AndAlso
                                            goto_next()
                                 Else
                                     Return False
                                 End If
                             End Function,
                             Function() As Boolean
                                 Return ec.end_result() AndAlso
                                        s.insert((+output).id) <> s.end() AndAlso
                                        goto_end()
                             End Function)
    End Function

    Public Function find_create_sub_node(ByVal name As String,
                                         ByVal output As pointer(Of node)) As eventComb
        Return p.create_get_set_data(Of [set](Of Int64), sub_nodes_property) _
                                    (internal_property_names.sub_nodes,
                                     Function(p As pointer(Of [set](Of Int64))) As eventComb
                                         Dim s As [set](Of Int64) = Nothing
                                         s = +p
                                         If s Is Nothing Then
                                             s = New [set](Of Int64)()
                                         End If
                                         Dim ec As eventComb = Nothing
                                         Return New eventComb(Function() As Boolean
                                                                  ec = find_create_sub_node(s, name, output)
                                                                  Return waitfor(ec) AndAlso
                                                                         goto_next()
                                                              End Function,
                                                              Function() As Boolean
                                                                  Return ec.end_result() AndAlso
                                                                         eva(p, s) AndAlso
                                                                         goto_end()
                                                              End Function)
                                     End Function)
    End Function

    Public Function sub_nodes(ByVal output As pointer(Of [set](Of Int64))) As eventComb
        Return p.get_data(internal_property_names.sub_nodes, output)
    End Function

    Public Function add_sub_node(ByVal id As Int64) As eventComb
        Return p.create_get_set_data(Of [set](Of Int64), sub_nodes_property) _
                                    (internal_property_names.sub_nodes,
                                     add_set_int64(id))
    End Function

    Public Function remove_sub_node(ByVal id As Int64) As eventComb
        Return p.create_get_set_data(Of [set](Of Int64), sub_nodes_property) _
                                    (internal_property_names.sub_nodes,
                                     remove_set_int64(id))
    End Function
End Class
